﻿
Imports osi.root.connector
Imports osi.root.template
Imports osi.root.formation
Imports osi.root.procedure
Imports osi.root.utils

Public Class lazier(Of T, TYPE_T As IComparable(Of TYPE_T), PARA_T As IComparable(Of PARA_T))
    Inherits selector(Of T, 
                         TYPE_T, 
                         PARA_T, 
                         multiton(Of T, PARA_T), 
                         multiton_alloc(Of T, PARA_T), 
                         multiton_invoke(Of T, PARA_T), 
                         lazier(Of T, PARA_T), 
                         lazier_alloc(Of T, PARA_T))
End Class

Public Class selector(Of T, TYPE_T As IComparable(Of TYPE_T), PARA_T As IComparable(Of PARA_T))
    Inherits selector(Of T, 
                         TYPE_T, 
                         PARA_T, 
                         singleton(Of T, PARA_T), 
                         singleton_alloc(Of T, PARA_T), 
                         singleton_invoke(Of T, PARA_T), 
                         selector(Of T, PARA_T), 
                         selector_alloc(Of T, PARA_T))
End Class

Public Class selector(Of T,
                         TYPE_T As IComparable(Of TYPE_T),
                         PARA_T As IComparable(Of PARA_T),
                         CT,
                         CT_ALLOC As __do(Of allocator(Of T, PARA_T), PARA_T, CT),
                         CT_INVOKE As __do(Of CT, pointer(Of T), event_comb),
                         ST As selector(Of T, PARA_T, CT, CT_ALLOC, CT_INVOKE),
                         ST_ALLOC As __do(Of allocator(Of T, PARA_T), ST))
    Private Shared ReadOnly selector_allocator As ST_ALLOC
    Private ReadOnly m As unique_strong_map(Of TYPE_T, ST)

    Shared Sub New()
        selector_allocator = alloc(Of ST_ALLOC)()
    End Sub

    Public Sub New()
        m = New unique_strong_map(Of TYPE_T, ST)()
    End Sub

    Public Function register(ByVal i As TYPE_T, ByVal a As allocator(Of T, PARA_T)) As Boolean
        If a Is Nothing Then
            Return False
        Else
            Return m.set(i, selector_allocator(a))
        End If
    End Function

    Public Function registered(ByVal i As TYPE_T) As Boolean
        Return m.exist(i)
    End Function

    Public Function [erase](ByVal t As TYPE_T) As Boolean
        Return m.erase(t)
    End Function

    Public Function [erase](ByVal ts As vector(Of TYPE_T)) As Boolean
        Return m.erase(ts)
    End Function

    Public Function [erase](ByVal t As TYPE_T, ByVal p As PARA_T) As Boolean
        Dim s As ST = Nothing
        Return m.get(t, s) AndAlso assert(Not s Is Nothing) AndAlso s.erase(p)
    End Function

    Public Function [erase](ByVal t As TYPE_T, ByVal ps As vector(Of PARA_T)) As Boolean
        Dim s As ST = Nothing
        Return m.get(t, s) AndAlso assert(Not s Is Nothing) AndAlso s.erase(ps)
    End Function

    Default Public ReadOnly Property allocate(ByVal i As TYPE_T,
                                              ByVal p As PARA_T,
                                              ByVal o As pointer(Of T)) As event_comb
        Get
            Dim ec As event_comb = Nothing
            Return New event_comb(Function() As Boolean
                                      Dim s As ST = Nothing
                                      If m.get(i, s) Then
                                          assert(Not s Is Nothing)
                                          ec = s(p, o)
                                          Return waitfor(ec) AndAlso
                                                 goto_next()
                                      Else
                                          Return False
                                      End If
                                  End Function,
                                  Function() As Boolean
                                      Return ec.end_result() AndAlso
                                             goto_end()
                                  End Function)
        End Get
    End Property
End Class
